package base.thread_example.example05;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedList;
import java.util.Random;

/**
 * 消息队列
 *
 * 异步模式之生产者/消费者
 * 3个线程负责不停生产(队列满了就暂停生产,直到不满继续启动生产)，1个线程负责消费
 *
 */
public class MessageQueueDemo {
    public static void main(String[] args) {
        MessageQueue queue = new MessageQueue(20);// 20个容量大小的队列

        for (int i = 0; i < 3; i++) {
            new Thread(()->{
                while (true) {
                    try {
                        queue.put(new Message(new Random().nextInt(100),"值-" + new Random().nextInt(200)));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"生产者-"+i).start();
        }


        new Thread(()->{
            while (true){
                try {
                    queue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"消费者").start();
    }
}

// 消息队列
class MessageQueue {
    private static final Logger log = LoggerFactory.getLogger(MessageQueue.class);
    // 消息队列容量
    private int capacity;
    // 消息队列集合
    private LinkedList<Message> list = new LinkedList<>();

    public MessageQueue(int capacity){
        this.capacity = capacity;
    }

    // 往队列存储数据
    public void put(Message msg) throws InterruptedException {
        synchronized (list){
            while (list.size() >= capacity){
                log.info("{}等待，队列已满",Thread.currentThread().getName());
                list.wait();
            }
            // 将消息添加到队列尾部
            list.addLast(msg);
            log.info("{} 已生产消息:->{}",Thread.currentThread().getName(), msg);
            list.notifyAll();
        }
    }

    // 从队列取数据
    public Message take() throws InterruptedException {
        synchronized (list){
            while (list.size() <= 0){
                log.info("{}等待，队列已空",Thread.currentThread().getName());
                list.wait();
            }
            Message msg = list.removeFirst();
            log.info("-------------------->{} 已消费消息:->{}",Thread.currentThread().getName(),msg);
            list.notifyAll();
            return msg;
        }
    }

}


// 消息队列存储的数据类型
class Message {
    private int id;
    private Object value;

    public Message(int id, Object value) {
        this.id = id;
        this.value = value;
    }

    public int getId() {
        return id;
    }

    public Object getValue() {
        return value;
    }

    @Override
    public String toString() {
        return "Message [id=" + id + ", value=" + value + "]";
    }

}
